Pré-requisitos
Pacotes necessários:
#if(!require(PSF)) install.packages("PSF")
#if(!require(timetk)) remotes::install_github("business-science/timetk")
if(!require(EflowStats)) remotes::install_github("USGS-R/EflowStats")
pacotes <- c(
"here",
"usethis",
"data.table",
"HEobs",
# "PSF",
"tidyverse",
"lubridate",
"fs",
"checkmate",
# "xts",
# "hydroGOF",
# "ModelMetrics",
# "forecast",
# "timetk",
"EflowStats",
"hydrostats",
#"NbClust",
# "cluster",
# "cluster.datasets",
"cowplot",
# "clValid",
"ggfortify",
#"clustree",
#"dendextend",
#"factoextra",
#"FactoMineR",
#"corrplot",
#"GGally",
#"ggiraphExtra",
"kableExtra",
"tidymodels",
"fasstr"
)
# Carregar os pacotes
easypackages::libraries(pacotes)
Scripts:
source(here('R', 'load-data.R'))
source(here('R', 'utils.R'))
Dados de vazão
Os dados importados de vazão devem ser regularmente espaçados no tempo. Esta adequação das séries diárias, se necessária, pode ser realizada com a função complete_dates() do pacote {lhmetools}. Assim assegura-se que todas estações possuam 1 observação por dia e sem datas faltantes.
Metadados
data_link <- "https://www.dropbox.com/s/d40adhw66uwueet/VazoesNaturaisONS_D_87UHEsDirceuAssis_2018.dat?dl=1"
qnat_meta <- extract_metadata(NA_character_, informative = TRUE)
glimpse(qnat_meta)
Dados
qnat_data <- qnat_dly_ons() %>%
select(date, qnat, code_stn) %>%
lhmetools::complete_dates(group = "code_stn")
glimpse(qnat_data)
# Incluindo nome da estacao
qnat_data <- qnat_data %>%
full_join(select(qnat_meta, estacao_codigo, nome_estacao),
by = c(code_stn = "estacao_codigo")
) %>%
rename("name_stn" = nome_estacao)
Assinaturas hidrológicas para 1 posto
Preparação dos dados para aplicação da função calc_magnifSeven com a opção de ano hidrológico (water year) para o posto 74 da ONS (G. B. Munhoz).
qnat_posto <- qnat_data %>%
sel_station(.,station = 74)
glimpse(qnat_posto)
summary(qnat_posto)
magnif7(stn_data = select(qnat_posto, date, qnat))
Dados agrupados por postos
by_stn <- qnat_data %>%
group_by(code_stn) %>%
nest()
Gráfico da sazonalidade da fração de vazão anual.
Fração mensal da vazão anual
# https://jcoliver.github.io/learn-r/008-ggplot-dendrograms-and-heatmaps.html
# glimpse(by_stn[["data"]][[1]])
q_mon_clim <- by_stn %>%
unnest(cols = "data") %>%
group_by(code_stn, month = lubridate::month(date)) %>%
select(-name_stn) %>%
summarise(q_med = mean(qnat, na.rm = TRUE))
q_ann_clim <- q_mon_clim %>%
summarise(q_tot = sum(q_med))
q_mon_clim <- q_mon_clim %>%
full_join(q_ann_clim) %>%
mutate(q_frac = q_med/q_tot * 100) %>%
ungroup() %>%
mutate(code_stn = as.factor(code_stn),
month = as.factor(month))
psych::describe(q_mon_clim) %>%
relocate(skew, kurtosis)
Agrupamento dos postos
qlong <- select(q_mon_clim, code_stn, month, q_frac) %>%
pivot_wider(names_from = "month",
values_from = "q_frac",
names_prefix = "qfrac_"
)
qlong_scaled <- qlong
qlong_scaled[,-1] <- scale(qlong_scaled[,-1])
# Run clustering
qmat <- as.matrix(qlong_scaled[, -1])
rownames(qmat) <- qlong_scaled$code_stn
clustd <- dist(x = qmat)
cd <- hclust(d = clustd, method="ward.D2")
#cd <- hclust(d = dist(x = qmat))
# optclus <- sapply(2:20,
# function(i)
# summary(cluster::silhouette(cutree(cd, k = i), clustd))$avg.width
# )
# optclus
# which.max(optclus) # 2
q_dendro <- as.dendrogram(cd)
# Create dendro
dendro_plot <- ggdendro::ggdendrogram(data = q_dendro, rotate = TRUE)+
theme(axis.text.y = element_text(size = 8))
# Preview the plot
dendro_plot
# linhas da ordem dos postos
q_order <- order.dendrogram(q_dendro)
# ordem dos postos
as.integer(as.vector(qlong_scaled$code_stn[q_order]))
Heat map da fração mensal da vazão anual com postos ordenados pelo agrupamento.
q_mon_clim_trans <- q_mon_clim %>%
mutate(code_stn = factor(x = code_stn,
levels = qlong_scaled$code_stn[q_order],
ordered = TRUE),
q_frac = round((q_frac/2))*2
)
# cbind(t = q_mon_clim_trans$q_frac, o = q_mon_clim$q_frac)
cols <- c("firebrick1", "lightpink3", "lightsteelblue3",
"cadetblue1", "cornflowerblue","blue", "navyblue")
q_mon_clim_trans %>%
ggplot(aes(x = month, y = code_stn)) +
geom_tile(aes(fill = q_frac), colour = "white") +
#geom_tile(aes(fill = factor(q_frac)), colour = "white") +
scale_x_discrete(expand = c(0,0)) +
theme_bw() +
#scale_fill_viridis_c()
#scale_fill_viridis_c(guide = "legend")
scale_fill_gradientn( "Vazão (% da média anual)",
colours = cols,
#guide = "legend",
breaks = seq(0, 20, by = 2)
) +
#scale_fill_manual(values = cols) +
theme(legend.title = element_text(angle = 90, vjust = 1),
legend.key.height = unit(1.5, units = "cm")
)
# scale_fill_distiller(
# palette='RdYlBu',
# direction = 1,
# breaks = seq(0, 20, by = 2),
# #guide = "legend"
# )
library(heatmaply)
index_cols <- c(8:12, 1:7) + 1
qdata <- as.data.frame(qlong[, index_cols])
names(qdata) <- tolower(month.abb[index_cols-1])
lut_postos <- qnat_data %>%
select(contains("stn")) %>%
distinct()
postos <- lut_postos$name_stn
postos <- setNames(postos, lut_postos$code_stn)
rownames(qdata) <- postos[as.character(qlong$code_stn)]
heatmaply(qdata,
k_row = 4,
Colv = FALSE,
#k_col = 3,
#scale = "column"
scale_fill_gradient_fun = scale_fill_gradientn( "Vazão \n (% da média anual)",
colours = cols,
#guide = "legend",
breaks = seq(0, 20, by = 2)
),
fontsize_row = 5
#seriate = "mean",
#seriate = "OLO"
#seriate = "GW"
#seriate = "none"
)
Testando fasstr
https://bcgov.github.io/fasstr/articles/fasstr.html
Será relevante considerar a diferenças nos períodos dos anos hidrológicos por posto?
check_season_plots <- qnat_data %>%
rename("Date" = date) %>%
fasstr::plot_daily_stats(
values = "qnat",
groups = "code_stn",
start_year = 1991,
end_year = 2010,
log_discharge = TRUE,
add_year = 2001,
complete_years = TRUE,
include_title = TRUE
)
codes <- names(check_season_plots) %>%
readr::parse_number()
lookup <- qnat_data %>%
select(contains("stn")) %>%
distinct() %>%
slice(order(codes)) %>%
arrange(code_stn)
plot_l <- map(seq_along(codes),
function(i) {
# i = 1
nm <- filter(lookup, code_stn == codes[i]) %>%
pull(name_stn)
check_season_plots[[i]] + ggtitle(paste0("Posto: ", nm))
})
plot_l
Assinaturas hidrológicas para todos postos
seven_stats <- by_stn %>%
#ungroup() %>%
mutate(stats = purrr::map(data, ~.x %>% select(date, qnat) %>% magnif7))
seven_stats_tidy <- seven_stats %>%
select(stats) %>%
unnest(cols = "stats") %>%
pivot_wider(names_from = indice, values_from = statistic) %>%
ungroup()
seven_stats_tidy
saveRDS(seven_stats_tidy, file = here("output", "seven_stats.RDS"))
LS0tCnRpdGxlOiAiQXNzaW5hdHVyYXMgaGlkcm9sw7NnaWNhcyBwYXJhIGJhY2lhcyBoaWRyb2dyw6FmaWNhcyBkbyBTSU4iCmF1dGhvcjogIkpEVCIKZGF0ZTogIjI0LzA1LzIwMjEiCm91dHB1dDogCiAgaHRtbF9kb2N1bWVudDogCiAgICB0b2M6IHllcwogIGh0bWxfbm90ZWJvb2s6IAogICAgdG9jOiB5ZXMKZWRpdG9yX29wdGlvbnM6IAogIGNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIFByw6ktcmVxdWlzaXRvcwoKUGFjb3RlcyBuZWNlc3PDoXJpb3M6CgpgYGB7ciwgbWVzc2FnZT1GQUxTRX0KI2lmKCFyZXF1aXJlKFBTRikpIGluc3RhbGwucGFja2FnZXMoIlBTRiIpCiNpZighcmVxdWlyZSh0aW1ldGspKSByZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiYnVzaW5lc3Mtc2NpZW5jZS90aW1ldGsiKQppZighcmVxdWlyZShFZmxvd1N0YXRzKSkgcmVtb3Rlczo6aW5zdGFsbF9naXRodWIoIlVTR1MtUi9FZmxvd1N0YXRzIikKCgpwYWNvdGVzIDwtIGMoCiAgImhlcmUiLAogICJ1c2V0aGlzIiwKICAiZGF0YS50YWJsZSIsCiAgIkhFb2JzIiwKIyAgIlBTRiIsCiAgInRpZHl2ZXJzZSIsCiAgImx1YnJpZGF0ZSIsCiAgImZzIiwKICAiY2hlY2ttYXRlIiwKIyAgInh0cyIsCiMgICJoeWRyb0dPRiIsCiMgICJNb2RlbE1ldHJpY3MiLAojICAiZm9yZWNhc3QiLAojICAidGltZXRrIiwKICAiRWZsb3dTdGF0cyIsCiAgImh5ZHJvc3RhdHMiLAogIyJOYkNsdXN0IiwKICMgICJjbHVzdGVyIiwgIAogIyAgImNsdXN0ZXIuZGF0YXNldHMiLCAKICAiY293cGxvdCIsIAogICMgImNsVmFsaWQiLAogICJnZ2ZvcnRpZnkiLCAKICAjImNsdXN0cmVlIiwKICAjImRlbmRleHRlbmQiLAogICMiZmFjdG9leHRyYSIsCiAgIyJGYWN0b01pbmVSIiwKICAjImNvcnJwbG90IiwKICAjIkdHYWxseSIsCiAgIyJnZ2lyYXBoRXh0cmEiLAogICJrYWJsZUV4dHJhIiwKICAidGlkeW1vZGVscyIsCiAgImZhc3N0ciIKKQojIENhcnJlZ2FyIG9zIHBhY290ZXMKZWFzeXBhY2thZ2VzOjpsaWJyYXJpZXMocGFjb3RlcykKYGBgCgpTY3JpcHRzOgoKYGBge3J9CnNvdXJjZShoZXJlKCdSJywgJ2xvYWQtZGF0YS5SJykpCnNvdXJjZShoZXJlKCdSJywgJ3V0aWxzLlInKSkKc291cmNlKGhlcmUoJ1InLCAncHJlcC1zdG4tZGF0YS5SJykpCmBgYAoKIyMgRGFkb3MgZGUgdmF6w6NvCgpPcyBkYWRvcyBpbXBvcnRhZG9zIGRlIHZhesOjbyBkZXZlbSBzZXIgcmVndWxhcm1lbnRlIGVzcGHDp2Fkb3Mgbm8gdGVtcG8uIEVzdGEgYWRlcXVhw6fDo28gZGFzIHPDqXJpZXMgZGnDoXJpYXMsIHNlIG5lY2Vzc8OhcmlhLCBwb2RlIHNlciByZWFsaXphZGEgY29tIGEgZnVuw6fDo28gYGNvbXBsZXRlX2RhdGVzKClgIGRvIHBhY290ZSAqKmB7bGhtZXRvb2xzfWAqKi4gQXNzaW0gYXNzZWd1cmEtc2UgcXVlIHRvZGFzIGVzdGHDp8O1ZXMgcG9zc3VhbSAxIG9ic2VydmHDp8OjbyBwb3IgZGlhIGUgc2VtIGRhdGFzIGZhbHRhbnRlcy4KCgpNZXRhZGFkb3MKCmBgYHtyfQpkYXRhX2xpbmsgPC0gImh0dHBzOi8vd3d3LmRyb3Bib3guY29tL3MvZDQwYWRodzY2dXd1ZWV0L1Zhem9lc05hdHVyYWlzT05TX0RfODdVSEVzRGlyY2V1QXNzaXNfMjAxOC5kYXQ/ZGw9MSIKcW5hdF9tZXRhIDwtIGV4dHJhY3RfbWV0YWRhdGEoTkFfY2hhcmFjdGVyXywgaW5mb3JtYXRpdmUgPSBUUlVFKQpnbGltcHNlKHFuYXRfbWV0YSkKYGBgCgoKRGFkb3MKCmBgYHtyfQpxbmF0X2RhdGEgPC0gcW5hdF9kbHlfb25zKCkgJT4lCiAgc2VsZWN0KGRhdGUsIHFuYXQsIGNvZGVfc3RuKSAlPiUKICBsaG1ldG9vbHM6OmNvbXBsZXRlX2RhdGVzKGdyb3VwID0gImNvZGVfc3RuIikKZ2xpbXBzZShxbmF0X2RhdGEpCgojIEluY2x1aW5kbyBub21lIGRhIGVzdGFjYW8KcW5hdF9kYXRhIDwtIHFuYXRfZGF0YSAlPiUKICBmdWxsX2pvaW4oc2VsZWN0KHFuYXRfbWV0YSwgZXN0YWNhb19jb2RpZ28sIG5vbWVfZXN0YWNhbyksCiAgICAgICAgICAgIGJ5ID0gYyhjb2RlX3N0biA9ICJlc3RhY2FvX2NvZGlnbyIpCiAgICAgICAgICAgICkgJT4lCiAgcmVuYW1lKCJuYW1lX3N0biIgPSBub21lX2VzdGFjYW8pCmBgYAoKIyMgQXNzaW5hdHVyYXMgaGlkcm9sw7NnaWNhcyBwYXJhIDEgcG9zdG8KCgoKClByZXBhcmHDp8OjbyBkb3MgZGFkb3MgcGFyYSBhcGxpY2HDp8OjbyBkYSBmdW7Dp8OjbyBgY2FsY19tYWduaWZTZXZlbmAgY29tIGEgb3DDp8OjbyBkZSBhbm8gaGlkcm9sw7NnaWNvICgqKndhdGVyIHllYXIqKikgcGFyYSBvIHBvc3RvIDc0IGRhIE9OUyAoRy4gQi4gTXVuaG96KS4KCmBgYHtyfQpxbmF0X3Bvc3RvIDwtIHFuYXRfZGF0YSAlPiUgCiAgc2VsX3N0YXRpb24oLixzdGF0aW9uID0gNzQpICAKZ2xpbXBzZShxbmF0X3Bvc3RvKQpzdW1tYXJ5KHFuYXRfcG9zdG8pCgptYWduaWY3KHN0bl9kYXRhID0gc2VsZWN0KHFuYXRfcG9zdG8sIGRhdGUsIHFuYXQpKQpgYGAKCgojIyBEYWRvcyBhZ3J1cGFkb3MgcG9yIHBvc3RvcwoKCgpgYGB7cn0KYnlfc3RuIDwtIHFuYXRfZGF0YSAlPiUgCiAgZ3JvdXBfYnkoY29kZV9zdG4pICU+JQogIG5lc3QoKQoKYGBgCgoKIyMjIEdyw6FmaWNvIGRhIHNhem9uYWxpZGFkZSBkYSBmcmHDp8OjbyBkZSB2YXrDo28gYW51YWwuCgpGcmHDp8OjbyBtZW5zYWwgZGEgdmF6w6NvIGFudWFsCgpgYGB7cn0KIyBodHRwczovL2pjb2xpdmVyLmdpdGh1Yi5pby9sZWFybi1yLzAwOC1nZ3Bsb3QtZGVuZHJvZ3JhbXMtYW5kLWhlYXRtYXBzLmh0bWwKIyBnbGltcHNlKGJ5X3N0bltbImRhdGEiXV1bWzFdXSkKCnFfbW9uX2NsaW0gPC0gYnlfc3RuICU+JQogIHVubmVzdChjb2xzID0gImRhdGEiKSAlPiUKICBncm91cF9ieShjb2RlX3N0biwgbW9udGggPSBsdWJyaWRhdGU6Om1vbnRoKGRhdGUpKSAlPiUKICBzZWxlY3QoLW5hbWVfc3RuKSAlPiUKICBzdW1tYXJpc2UocV9tZWQgPSBtZWFuKHFuYXQsIG5hLnJtID0gVFJVRSkpCgpxX2Fubl9jbGltIDwtIHFfbW9uX2NsaW0gJT4lCiAgc3VtbWFyaXNlKHFfdG90ID0gc3VtKHFfbWVkKSkKCnFfbW9uX2NsaW0gPC0gcV9tb25fY2xpbSAlPiUgCiAgZnVsbF9qb2luKHFfYW5uX2NsaW0pICU+JQogIG11dGF0ZShxX2ZyYWMgPSBxX21lZC9xX3RvdCAqIDEwMCkgJT4lCiAgdW5ncm91cCgpICU+JSAgCiAgbXV0YXRlKGNvZGVfc3RuID0gYXMuZmFjdG9yKGNvZGVfc3RuKSwKICAgICAgICAgbW9udGggPSBhcy5mYWN0b3IobW9udGgpKQogIApwc3ljaDo6ZGVzY3JpYmUocV9tb25fY2xpbSkgJT4lIAogIHJlbG9jYXRlKHNrZXcsIGt1cnRvc2lzKQpgYGAKCgpBZ3J1cGFtZW50byBkb3MgcG9zdG9zCgpgYGB7cn0KcWxvbmcgPC0gc2VsZWN0KHFfbW9uX2NsaW0sIGNvZGVfc3RuLCBtb250aCwgcV9mcmFjKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gIm1vbnRoIiwgCiAgICAgICAgICAgICAgdmFsdWVzX2Zyb20gPSAicV9mcmFjIiwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAicWZyYWNfIgogICAgICAgICAgICAgICkKcWxvbmdfc2NhbGVkIDwtIHFsb25nIApxbG9uZ19zY2FsZWRbLC0xXSA8LSBzY2FsZShxbG9uZ19zY2FsZWRbLC0xXSkKCiMgUnVuIGNsdXN0ZXJpbmcKcW1hdCA8LSBhcy5tYXRyaXgocWxvbmdfc2NhbGVkWywgLTFdKQpyb3duYW1lcyhxbWF0KSA8LSBxbG9uZ19zY2FsZWQkY29kZV9zdG4KCmNsdXN0ZCA8LSBkaXN0KHggPSBxbWF0KQpjZCA8LSBoY2x1c3QoZCA9IGNsdXN0ZCwgbWV0aG9kPSJ3YXJkLkQyIikKI2NkIDwtIGhjbHVzdChkID0gZGlzdCh4ID0gcW1hdCkpCiMgb3B0Y2x1cyA8LSBzYXBwbHkoMjoyMCwgCiMgICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uKGkpIAojICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnkoY2x1c3Rlcjo6c2lsaG91ZXR0ZShjdXRyZWUoY2QsIGsgPSBpKSwgY2x1c3RkKSkkYXZnLndpZHRoCiMgICAgICAgICAgICAgICAgICAgICkKIyBvcHRjbHVzCiMgd2hpY2gubWF4KG9wdGNsdXMpICMgMgpxX2RlbmRybyA8LSBhcy5kZW5kcm9ncmFtKGNkKQoKIyBDcmVhdGUgZGVuZHJvCmRlbmRyb19wbG90IDwtIGdnZGVuZHJvOjpnZ2RlbmRyb2dyYW0oZGF0YSA9IHFfZGVuZHJvLCByb3RhdGUgPSBUUlVFKSsKICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQoKIyBQcmV2aWV3IHRoZSBwbG90CmRlbmRyb19wbG90CgojIGxpbmhhcyBkYSBvcmRlbSBkb3MgcG9zdG9zCnFfb3JkZXIgPC0gb3JkZXIuZGVuZHJvZ3JhbShxX2RlbmRybykKIyBvcmRlbSBkb3MgcG9zdG9zCmFzLmludGVnZXIoYXMudmVjdG9yKHFsb25nX3NjYWxlZCRjb2RlX3N0bltxX29yZGVyXSkpCmBgYAoKSGVhdCBtYXAgZGEgZnJhw6fDo28gbWVuc2FsIGRhIHZhesOjbyBhbnVhbCBjb20gcG9zdG9zIG9yZGVuYWRvcyBwZWxvIGFncnVwYW1lbnRvLgoKYGBge3J9CnFfbW9uX2NsaW1fdHJhbnMgPC0gIHFfbW9uX2NsaW0gJT4lCiAgbXV0YXRlKGNvZGVfc3RuID0gZmFjdG9yKHggPSBjb2RlX3N0biwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscyA9IHFsb25nX3NjYWxlZCRjb2RlX3N0bltxX29yZGVyXSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkID0gVFJVRSksCiAgICAgICAgIHFfZnJhYyA9IHJvdW5kKChxX2ZyYWMvMikpKjIKICAgICAgICAgKQoKIyBjYmluZCh0ID0gcV9tb25fY2xpbV90cmFucyRxX2ZyYWMsIG8gPSBxX21vbl9jbGltJHFfZnJhYykKY29scyA8LSBjKCJmaXJlYnJpY2sxIiwgImxpZ2h0cGluazMiLCAibGlnaHRzdGVlbGJsdWUzIiwgCiAgICAgICAgICAiY2FkZXRibHVlMSIsICJjb3JuZmxvd2VyYmx1ZSIsImJsdWUiLCAibmF2eWJsdWUiKQoKcV9tb25fY2xpbV90cmFucyAlPiUKICAKICBnZ3Bsb3QoYWVzKHggPSBtb250aCwgeSA9IGNvZGVfc3RuKSkgKwogIGdlb21fdGlsZShhZXMoZmlsbCA9IHFfZnJhYyksIGNvbG91ciA9ICJ3aGl0ZSIpICsKICAjZ2VvbV90aWxlKGFlcyhmaWxsID0gZmFjdG9yKHFfZnJhYykpLCBjb2xvdXIgPSAid2hpdGUiKSArCiAgc2NhbGVfeF9kaXNjcmV0ZShleHBhbmQgPSBjKDAsMCkpICsKICB0aGVtZV9idygpICsKICAjc2NhbGVfZmlsbF92aXJpZGlzX2MoKQogICNzY2FsZV9maWxsX3ZpcmlkaXNfYyhndWlkZSA9ICJsZWdlbmQiKQogIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKCAiVmF6w6NvICglIGRhIG3DqWRpYSBhbnVhbCkiLAogICAgICAgICAgICAgICAgICAgICAgIGNvbG91cnMgPSBjb2xzLAogICAgICAgICAgICAgICAgICAgICAgICNndWlkZSA9ICJsZWdlbmQiLAogICAgICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IHNlcSgwLCAyMCwgYnkgPSAyKQogICAgICAgICAgICAgICAgICAgICAgICkgKwogICNzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjb2xzKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMSksCiAgICAgICAgbGVnZW5kLmtleS5oZWlnaHQgPSB1bml0KDEuNSwgdW5pdHMgPSAiY20iKQogICAgICAgICkKCiAgICAjIHNjYWxlX2ZpbGxfZGlzdGlsbGVyKAogICAgIyAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlPSdSZFlsQnUnLCAKICAgICMgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uID0gMSwKICAgICMgICAgICAgICAgICAgICAgICAgICAgYnJlYWtzID0gc2VxKDAsIDIwLCBieSA9IDIpLAogICAgIyAgICAgICAgICAgICAgICAgICAgICAjZ3VpZGUgPSAibGVnZW5kIgogICAgIyAgICAgICAgICAgICAgICAgICAgICkKICAKCgpgYGAKCmBgYHtyLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD04fQpsaWJyYXJ5KGhlYXRtYXBseSkKaW5kZXhfY29scyA8LSBjKDg6MTIsIDE6NykgKyAxCnFkYXRhIDwtIGFzLmRhdGEuZnJhbWUocWxvbmdbLCBpbmRleF9jb2xzXSkKbmFtZXMocWRhdGEpIDwtIHRvbG93ZXIobW9udGguYWJiW2luZGV4X2NvbHMtMV0pCgpsdXRfcG9zdG9zIDwtIHFuYXRfZGF0YSAlPiUgCiAgc2VsZWN0KGNvbnRhaW5zKCJzdG4iKSkgJT4lIAogIGRpc3RpbmN0KCkgCnBvc3RvcyA8LSBsdXRfcG9zdG9zJG5hbWVfc3RuCnBvc3RvcyA8LSBzZXROYW1lcyhwb3N0b3MsIGx1dF9wb3N0b3MkY29kZV9zdG4pCiAgCnJvd25hbWVzKHFkYXRhKSA8LSBwb3N0b3NbYXMuY2hhcmFjdGVyKHFsb25nJGNvZGVfc3RuKV0KCmhlYXRtYXBseShxZGF0YSwgCiAgICAgICAgICBrX3JvdyA9IDQsIAogICAgICAgICAgQ29sdiA9IEZBTFNFLAogICAgICAgICAgI2tfY29sID0gMywgCiAgICAgICAgICAjc2NhbGUgPSAiY29sdW1uIgogICAgICAgICAgc2NhbGVfZmlsbF9ncmFkaWVudF9mdW4gPSBzY2FsZV9maWxsX2dyYWRpZW50biggIlZhesOjbyBcbiAoJSBkYSBtw6lkaWEgYW51YWwpIiwKICAgICAgICAgICAgICAgICAgICAgICBjb2xvdXJzID0gY29scywKICAgICAgICAgICAgICAgICAgICAgICAjZ3VpZGUgPSAibGVnZW5kIiwKICAgICAgICAgICAgICAgICAgICAgICBicmVha3MgPSBzZXEoMCwgMjAsIGJ5ID0gMikKICAgICAgICAgICAgICAgICAgICAgICApLAogICAgICAgICAgZm9udHNpemVfcm93ID0gNgogICAgICAgICAgI3NlcmlhdGUgPSAibWVhbiIsCiAgICAgICAgICAjc2VyaWF0ZSA9ICJPTE8iCiAgICAgICAgICAjc2VyaWF0ZSA9ICJHVyIKICAgICAgICAgICNzZXJpYXRlID0gIm5vbmUiCiAgICAgICAgICApCmBgYAoKCiMjIFRlc3RhbmRvIGZhc3N0cgoKaHR0cHM6Ly9iY2dvdi5naXRodWIuaW8vZmFzc3RyL2FydGljbGVzL2Zhc3N0ci5odG1sCgpTZXLDoSByZWxldmFudGUgY29uc2lkZXJhciBhIGRpZmVyZW7Dp2FzIG5vcyBwZXLDrW9kb3MgZG9zIGFub3MgaGlkcm9sw7NnaWNvcyBwb3IgcG9zdG8/CgpgYGB7ciwgZXZhbCA9IEZBTFNFfQoKY2hlY2tfc2Vhc29uX3Bsb3RzIDwtIHFuYXRfZGF0YSAlPiUKICByZW5hbWUoIkRhdGUiID0gZGF0ZSkgJT4lCiAgZmFzc3RyOjpwbG90X2RhaWx5X3N0YXRzKAogICAgdmFsdWVzID0gInFuYXQiLAogICAgZ3JvdXBzID0gImNvZGVfc3RuIiwKICAgIHN0YXJ0X3llYXIgPSAxOTkxLAogICAgZW5kX3llYXIgPSAyMDEwLAogICAgbG9nX2Rpc2NoYXJnZSA9IFRSVUUsCiAgICBhZGRfeWVhciA9IDIwMDEsIAogICAgY29tcGxldGVfeWVhcnMgPSBUUlVFLCAKICAgIGluY2x1ZGVfdGl0bGUgPSBUUlVFCiAgKQoKCmBgYAoKCmBgYHtyLCBldmFsID0gRkFMU0V9CmNvZGVzIDwtIG5hbWVzKGNoZWNrX3NlYXNvbl9wbG90cykgJT4lCiAgcmVhZHI6OnBhcnNlX251bWJlcigpCgpsb29rdXAgPC0gcW5hdF9kYXRhICU+JSAKICBzZWxlY3QoY29udGFpbnMoInN0biIpKSAlPiUgCiAgZGlzdGluY3QoKSAlPiUKICBzbGljZShvcmRlcihjb2RlcykpICU+JQogIGFycmFuZ2UoY29kZV9zdG4pCgpwbG90X2wgPC0gbWFwKHNlcV9hbG9uZyhjb2RlcyksIAogICAgZnVuY3Rpb24oaSkgewogICAgICAjIGkgPSAxCiAgICAgIG5tIDwtIGZpbHRlcihsb29rdXAsIGNvZGVfc3RuID09IGNvZGVzW2ldKSAlPiUKICAgICAgICBwdWxsKG5hbWVfc3RuKQogICAgICBjaGVja19zZWFzb25fcGxvdHNbW2ldXSArIGdndGl0bGUocGFzdGUwKCJQb3N0bzogIiwgbm0pKQogICAgfSkKcGxvdF9sCmBgYAoKIyMgQXNzaW5hdHVyYXMgaGlkcm9sw7NnaWNhcyBwYXJhIHRvZG9zIHBvc3RvcwoKCgpgYGB7cn0Kc2V2ZW5fc3RhdHMgPC0gYnlfc3RuICU+JQogICN1bmdyb3VwKCkgJT4lCiAgbXV0YXRlKHN0YXRzID0gcHVycnI6Om1hcChkYXRhLCB+LnggJT4lIHNlbGVjdChkYXRlLCBxbmF0KSAlPiUgbWFnbmlmNykpCmBgYAoKCgpgYGB7cn0Kc2V2ZW5fc3RhdHNfdGlkeSA8LSBzZXZlbl9zdGF0cyAlPiUKICBzZWxlY3Qoc3RhdHMpICU+JQogIHVubmVzdChjb2xzID0gInN0YXRzIikgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IGluZGljZSwgdmFsdWVzX2Zyb20gPSBzdGF0aXN0aWMpICU+JQogIHVuZ3JvdXAoKQpzZXZlbl9zdGF0c190aWR5CnNhdmVSRFMoc2V2ZW5fc3RhdHNfdGlkeSwgZmlsZSA9IGhlcmUoIm91dHB1dCIsICJzZXZlbl9zdGF0cy5SRFMiKSkKYGBgCgo=